package com.catmiw.wyz;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.ClientAnchor;
import org.apache.poi.ss.usermodel.CreationHelper;
import org.apache.poi.ss.usermodel.Drawing;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.Hyperlink;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.Picture;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;

import com.catmiw.wyz.util.ExcelUtils;
import com.catmiw.wyz.util.NetUtils;

class Processor implements Runnable {
	private int id;
	private List<Book> books = null;
	private int[] tags = null;
	private int nowprocess = 0;
	private int count = 0;

	public Processor(int id, List<Book> books, int[] tags) {
		this.id = id;
		this.books = books;
		this.tags = tags;
	}

	public void run() {
		while (true) {
			nowprocess = -1;
			synchronized (tags) {
				for (int i = 0; i < tags.length; i++) {
					if (tags[i] == 0) {
						tags[i] = 1;
						nowprocess = i;
						break;
					}
				}
			}
			if (nowprocess == -1) {
				System.out.println("Thread " + id + " is finished!  " + count);
				break;
			}
			Book book = books.get(nowprocess);
			count++;
			//System.out.println("Thread " + id + ": " + book);
			DangdangQuery.loadBook(book);
			synchronized (tags) {
				tags[nowprocess] = 2;
			}
		}
	}
}

public class DangdangQuery {
	private CellStyle[] style = null;
	private CellStyle[] stylebuy = null;
	private CellStyle[] styleok = null;
	private Font[] font = null;

	private String xlsfilename=null;
	public DangdangQuery(String xlsfilename) {
		this.xlsfilename=xlsfilename;
		wb = ExcelUtils.getWorkbook(xlsfilename);
		
		Sheet sheet=wb.getSheetAt(0);
		Row row=sheet.getRow(0);
		for (int i=1;i<wb.getNumberOfSheets();i++){
			Sheet sheet2=wb.getSheetAt(i);
			for (short j=0;j<=row.getLastCellNum();j++){
				sheet2.setColumnWidth(j, sheet.getColumnWidth(j));
			}
		}

		style = new CellStyle[4];
		stylebuy = new CellStyle[4];
		styleok = new CellStyle[4];
		font = new Font[3];
		font[0] = wb.createFont();
		font[0].setFontName("微软雅黑");
		font[0].setFontHeightInPoints((short) 10);
		font[1] = wb.createFont();
		font[1].setFontName("微软雅黑");
		font[1].setFontHeightInPoints((short) 10);
		font[1].setUnderline(Font.U_SINGLE);
		font[1].setColor(IndexedColors.BLUE.getIndex());
		font[2] = wb.createFont();
		font[2].setFontName("微软雅黑");
		font[2].setFontHeightInPoints((short) 10);
		font[2].setColor(IndexedColors.RED.getIndex());

		for (int i=0;i<style.length;i++){
			style[i] = wb.createCellStyle();
			stylebuy[i] = wb.createCellStyle();
			styleok[i] = wb.createCellStyle();
		}
		style[0].setFont(font[0]);
		style[0].setBorderBottom(CellStyle.BORDER_THIN);
		style[0].setBorderLeft(CellStyle.BORDER_THIN);
		style[0].setBorderRight(CellStyle.BORDER_THIN);
		style[0].setBorderTop(CellStyle.BORDER_THIN);
		style[0].setAlignment(CellStyle.ALIGN_CENTER);
		style[0].setVerticalAlignment(CellStyle.VERTICAL_CENTER);

		style[1].cloneStyleFrom(style[0]);
		style[1].setAlignment(CellStyle.ALIGN_LEFT);

		style[2].cloneStyleFrom(style[0]);
		style[2].setAlignment(CellStyle.ALIGN_RIGHT);

		style[3].cloneStyleFrom(style[0]);
		style[3].setFont(font[1]);
		
		stylebuy[0].cloneStyleFrom(style[0]);
		stylebuy[0].setFillForegroundColor(IndexedColors.LIGHT_YELLOW.getIndex());
		stylebuy[0].setFillPattern(CellStyle.SOLID_FOREGROUND);
		stylebuy[1].cloneStyleFrom(style[1]);
		stylebuy[1].setFillForegroundColor(IndexedColors.LIGHT_YELLOW.getIndex());
		stylebuy[1].setFillPattern(CellStyle.SOLID_FOREGROUND);
		stylebuy[2].cloneStyleFrom(style[2]);
		stylebuy[2].setFillForegroundColor(IndexedColors.LIGHT_YELLOW.getIndex());
		stylebuy[2].setFillPattern(CellStyle.SOLID_FOREGROUND);
		stylebuy[3].cloneStyleFrom(style[3]);
		stylebuy[3].setFillForegroundColor(IndexedColors.LIGHT_YELLOW.getIndex());
		stylebuy[3].setFillPattern(CellStyle.SOLID_FOREGROUND);

		styleok[0].cloneStyleFrom(style[0]);
		styleok[0].setFont(font[2]);
		styleok[1].cloneStyleFrom(style[1]);
		styleok[1].setFont(font[2]);
		styleok[2].cloneStyleFrom(style[2]);
		styleok[2].setFont(font[2]);
		styleok[3].cloneStyleFrom(style[3]);
		styleok[3].setFont(font[2]);

	}

	private Workbook wb = null;

	public static String BOOKINFOQUERYURL = "http://product.dangdang.com/product.aspx?product_id=";
	public static String XLSFILENAME = "D:\\王奕卓的教育\\家庭教育计划\\王奕卓书单.xls";

	public static String patternMatch(String st, String regEx, int headlen,
			int taillen) {
		String result = null;

		Pattern p = Pattern.compile(regEx);
		Matcher m = p.matcher(st);
		if (m.find()) {
			// System.out.println(m.start()+"\t"+m.end());
			result = st.substring(m.start() + headlen, m.end() - taillen);
		}

		return result;
	}

	public static String escapeTag(String source) {
		if (source == null)
			return "";

		StringBuffer sb = new StringBuffer(source);
		while (sb.indexOf("<") >= 0) {
			int posb = sb.indexOf("<");
			int pose = sb.indexOf(">", posb);
			if (pose > 0) {
				//String temp = sb.substring(posb, pose);
				sb.replace(posb, pose + 1, "");
			} else {
				break;
			}
		}
		return sb.toString();
	}

	public static void writePic(Workbook wb, Sheet sheet, int row, int col,
			byte[] pic) {
		int pictureIdx = wb.addPicture(pic, Workbook.PICTURE_TYPE_JPEG);
		CreationHelper helper = wb.getCreationHelper();
		Drawing drawing = sheet.createDrawingPatriarch();
		ClientAnchor anchor = helper.createClientAnchor();
		anchor.setCol1(row);
		anchor.setRow1(col);
		Picture pict = drawing.createPicture(anchor, pictureIdx);

		pict.resize(0.3);
		// pict.

	}

	public static int BOOKNAMEMAXLEN = 28;
	public static int AUTHORNAMEMAXLEN = 10;

	public static void loadBook(Book book) {
		String url = BOOKINFOQUERYURL + book.getDangdangid();
		System.out.println(book.getId() + "\t" + url);

		String st = NetUtils.getResponseFromNet(url);
		if (st==null)
			return;

		String regEx = "<h1>[\\s\\S]*?</h1>";
		String bookname = patternMatch(st, regEx, 4, 5);
		if (bookname==null)
			bookname="";
		if (bookname.contains("<")){
			bookname=bookname.substring(0,bookname.indexOf("<"));
		}
		
		bookname = bookname.length() > BOOKNAMEMAXLEN ? bookname.substring(0,
				BOOKNAMEMAXLEN) : bookname;

		regEx = "<img src=\"[\\w\\:\\/\\.\\d\\-]*?_b\\.jpg\"";
		String picurl = patternMatch(st, regEx, 10, 1);

		//regEx = "<span class=\"num\">￥\\d*.\\d*</span>";
		regEx = "<p>当 当 价：<b id=\"d_price\" class=\"d_price \"><span class=\"yen\">&yen;</span>\\d*.\\d*";
		String ddprice = patternMatch(st, regEx, 0, 0);
		if (ddprice == null) {
			regEx = "<span class=\"promotions_price_d\">￥<b>\\d*.\\d*</b>";
			ddprice = patternMatch(st, regEx, 0, 0);
		}
		if (ddprice == null) {
			regEx = "<p>当 当 价：<b id=\"d_price\" class=\"d_price gray\"><span class=\"yen\">&yen;</span>\\d*.\\d*</b>";
			ddprice = patternMatch(st, regEx, 0, 0);
		}
		
		if (ddprice != null) {
			ddprice = patternMatch(ddprice, "\\d{1,5}.\\d{2}", 0, 0);
		}

		//<p>当 当 价：<b id="d_price" class="d_price "><span class="yen">&yen;</span>7.80</b><span class="break"></span></p>
		//regEx = "<p class=\"price_m\">定[\\s\\S]*?价\\：￥\\d*.\\d*";
		
		regEx = "<i class=\"m_price\">&yen;\\d*.\\d*";
		//regEx = "<p>当 当 价：<b id=\"d_price\" class=\"d_price \"><span class=\"yen\">&yen;</span>\\d*.\\d*";
		String price = patternMatch(st, regEx, 24, 0);
		System.out.println(book.getId()+bookname+"\t"+price+"\t"+ddprice);
		if (price==null)
			price="0.0";
		if (price.length() > 10) {
			price=price.replace("class=\"d_price \"><span class=\"yen\">&yen;</span>", "");
			System.out.println(price);
//			return;
		}

		regEx = "<p>作　　者\\：[\\s\\S]*?</p>";
		String author = escapeTag(patternMatch(st, regEx, 8, 0));
		author = author.length() > AUTHORNAMEMAXLEN ? author.substring(0,
				AUTHORNAMEMAXLEN) : author;

		regEx = "<p>出 版 社\\：[\\s\\S]*?</p>";
		String publisher = escapeTag(patternMatch(st, regEx, 0, 0));

		regEx = "<span>I S B N：\\d*</span>";
		String isbn = escapeTag(patternMatch(st, regEx, 14, 7));

		//byte[] pic = NetUtils.getFileBytesStreamFromNet(picurl);
		//byte[] pic =null;

		book.setAuthor(author);
		double d = 0;
		try{
			d=Double.parseDouble(ddprice);
		} catch (Exception e){
			System.out.println("ddprice:"+ddprice);
			e.printStackTrace();
		}
		book.setDangdangprice(d);
		List<Double> pl = book.getPricelist();
		if (!pl.contains(d)) {
			pl.add(d);
		}

		book.setIsbn(isbn);
		book.setName(bookname);
		//book.setPicture(pic);
		book.setPrice(Double.parseDouble(price));
		book.setPublisher(publisher.length() == 0 ? "" : publisher.substring(6,
				publisher.length()));

		// System.out.println(book);
	}

	public void writerow(Sheet sheet, Book book) {
		for (int i = 1; i <= sheet.getLastRowNum(); i++) {
			List<Double> pl = book.getPricelist();
			Collections.sort(pl);
			boolean ok=false;
			if (book.getDangdangprice()>0&&book.getDangdangprice()>0&&book.getPrice()>0)
				ok=(book.getDangdangprice()==pl.get(0)&&pl.size()>1)||(book.getDangdangprice()/book.getPrice()<=0.395);

			Row row = sheet.getRow(i);
			if (row==null)
				continue;
			Cell cell = row.getCell(0);
			if (cell==null)
				continue;
			
			double d = cell.getNumericCellValue();
			if (d < 1)
				continue;
			
			if (book.getId() == new Double(d).intValue()&&pl.size()>0) {
				cell.setCellStyle("√".equals(book.getBuytag())?stylebuy[0]:(ok?styleok[0]:style[0]));
				
				cell = (row.getCell(1) == null) ? row.createCell(1) : row
						.getCell(1);
				cell.setCellStyle("√".equals(book.getBuytag())?stylebuy[1]:(ok?styleok[1]:style[1]));

				cell = (row.getCell(3) == null) ? row.createCell(3) : row
						.getCell(3);
				cell.setCellStyle("√".equals(book.getBuytag())?stylebuy[0]:(ok?styleok[0]:style[0]));

				cell = (row.getCell(2) == null) ? row.createCell(2) : row
						.getCell(2);
				cell.setCellValue(book.getName());
				cell.setCellStyle("√".equals(book.getBuytag())?stylebuy[1]:(ok?styleok[1]:style[1]));

				cell = (row.getCell(4) == null) ? row.createCell(4) : row
						.getCell(4);
				cell.setCellValue(book.getAuthor());
				cell.setCellStyle("√".equals(book.getBuytag())?stylebuy[1]:(ok?styleok[1]:style[1]));

				cell = (row.getCell(5) == null) ? row.createCell(5) : row
						.getCell(5);
				cell.setCellValue(book.getPublisher());
				cell.setCellStyle("√".equals(book.getBuytag())?stylebuy[1]:(ok?styleok[1]:style[1]));

				cell = (row.getCell(6) == null) ? row.createCell(6) : row
						.getCell(6);
				cell.setCellValue(book.getIsbn());
				cell.setCellStyle("√".equals(book.getBuytag())?stylebuy[1]:(ok?styleok[1]:style[1]));

				cell = (row.getCell(7) == null) ? row.createCell(7) : row
						.getCell(7);
				cell.setCellValue(book.getPrice());
				cell.setCellStyle("√".equals(book.getBuytag())?stylebuy[2]:(ok?styleok[2]:style[2]));

				cell = (row.getCell(8) == null) ? row.createCell(8) : row
						.getCell(8);
				cell.setCellValue(book.getDangdangprice());
				cell.setCellStyle("√".equals(book.getBuytag())?stylebuy[2]:(ok?styleok[2]:style[2]));

				if (pl.size() > 0) {
					cell = (row.getCell(15) == null) ? row.createCell(15) : row
							.getCell(15);
					cell.setCellValue(pl.get(pl.size() - 1));
					cell.setCellStyle("√".equals(book.getBuytag())?stylebuy[2]:(ok?styleok[2]:style[2]));
				}

				for (int j = 0; j < 5; j++) {
					if (j < pl.size()) {
						cell = (row.getCell(10 + j) == null) ? row
								.createCell(10 + j) : row.getCell(10 + j);
						cell.setCellValue(pl.get(j));
						cell.setCellStyle("√".equals(book.getBuytag())?stylebuy[2]:(ok?styleok[2]:style[2]));
					} else {
						cell = (row.getCell(10 + j) == null) ? row
								.createCell(10 + j) : row.getCell(10 + j);
						cell.setCellStyle("√".equals(book.getBuytag())?stylebuy[2]:(ok?styleok[2]:style[2]));
					}
				}

				cell = (row.getCell(9) == null) ? row.createCell(9) : row
						.getCell(9);
				//System.out.println(((int)(book.getDangdangprice()*100/book.getPrice()))/10.0);
				cell.setCellValue(((int)(book.getDangdangprice()*100/book.getPrice()))/10.0);
				cell.setCellStyle("√".equals(book.getBuytag())?stylebuy[2]:(ok?styleok[2]:style[2]));

				cell = (row.getCell(16) == null) ? row.createCell(16) : row
						.getCell(16);
				cell.setCellValue(book.getDangdangprice()-pl.get(0));
				cell.setCellStyle("√".equals(book.getBuytag())?stylebuy[2]:(ok?styleok[2]:style[2]));

				cell = (row.getCell(17) == null) ? row.createCell(17) : row
						.getCell(17);
				cell.setCellValue(pl.get(pl.size() - 1)-book.getDangdangprice());
				cell.setCellStyle("√".equals(book.getBuytag())?stylebuy[2]:(ok?styleok[2]:style[2]));

				cell = (row.getCell(18) == null) ? row.createCell(18) : row
						.getCell(18);
				cell.setCellValue("购买");
				Hyperlink link = wb.getCreationHelper()
						.createHyperlink(Hyperlink.LINK_URL);
				link.setAddress(BOOKINFOQUERYURL + book.getDangdangid());
				cell.setHyperlink(link);
				cell.setCellStyle("√".equals(book.getBuytag())?stylebuy[3]:(ok?styleok[3]:style[3]));

				break;
			}
		}
	}

	public void writeback(Sheet sheet, List<Book> books) {
		for (Book book : books) {
			writerow(sheet, book);
		}

		ExcelUtils.writeWorkbook(wb, xlsfilename);
	}

	public List<Book> getBookList(Sheet sheet) {
		List<Book> result = new ArrayList<Book>();

		for (int i = 1; i <= sheet.getLastRowNum(); i++) {
			Row row = sheet.getRow(i);
			if (row==null)
				continue;
			Cell cell = row.getCell(0);
			if (cell==null)
				continue;

			double d = cell.getNumericCellValue();
			if (d < 1)
				continue;

			Book book = new Book(new Double(d).intValue());
			book.setSheetname(sheet.getSheetName());
			
			cell = row.getCell(1);
			if (cell==null)
				continue;
			d = cell.getNumericCellValue();
			if (d < 1)
				continue;

			List<Double> pl = new ArrayList<Double>();
			book.setPricelist(pl);

			book.setDangdangid("" + new Double(d).intValue());

			cell = row.getCell(3);
			book.setBuytag((cell == null) ? "" : cell.getStringCellValue());

			for (int j = 10; j <= 15; j++) {
				cell = row.getCell(j);
				if (cell != null) {
					d = cell.getNumericCellValue();
					if (d > 0.0 && (!pl.contains(d)))
						pl.add(d);
				}
			}

			if (!result.contains(book))
				result.add(book);
			else {
				throw new RuntimeException("出现了重复的行号："+book.getId());
			}
		}

		return result;
	}

	public static int MAXTHREADS = 10;

	public void updateSheet(Sheet sheet) {
		if (sheet.getSheetName().indexOf("Sheet")>=0)
			return;
		
		System.out.println("正在处理 <"+sheet.getSheetName()+"> 中的书单...");
		List<Book> books = getBookList(sheet);
		int[] tags = new int[books.size()];

		for (int i = 0; i < MAXTHREADS; i++) {
			new Thread(new Processor(i, books, tags)).start();
		}

		boolean finished = false;
		while (!finished) {
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			finished = true;
			synchronized (tags) {
				for (int i = 0; i < tags.length; i++) {
					if (tags[i] < 2) {
						finished = false;
						break;
					}
				}
			}
			if (finished) {
				writeback(sheet, books);
				System.out.println(sheet.getSheetName() + " is finished!!");
			}
		}

	}

	public void updateSheet(String sheetname) {
		Sheet sheet = wb.getSheet(sheetname);
		if (sheet != null) {
			updateSheet(sheet);
		}
	}

	public void updateSheet(String[] sheetnames) {
		for (String s : sheetnames) {
			Sheet sheet = wb.getSheet(s);
			if (sheet != null) {
				updateSheet(sheet);
			}
		}
	}

	public void updateAllSheet() {
		for (int k = 0; k < wb.getNumberOfSheets(); k++) {
			Sheet sheet = wb.getSheetAt(k);
			updateSheet(sheet);
		}
	}

	public void updateExcept(String[] sheetnames){
		List<String> sns=new ArrayList<String>();
		for (String s:sheetnames){
			sns.add(s);
		}
		
		for (int k = 0; k < wb.getNumberOfSheets(); k++) {
			Sheet sheet = wb.getSheetAt(k);
			if (!sns.contains(sheet.getSheetName()))
				updateSheet(sheet);
		}
	}
	
	public static void main(String[] args) {
		DangdangQuery ddq = new DangdangQuery(XLSFILENAME);
		ddq.updateAllSheet();
		//ddq.updateSheet(new String[]{"杨红樱系列"});
		//ddq.updateExcept(new String[]{"百年百部","国际大奖小说","猫武士","奥数"});
	}

}
